package com.qf.service.impl;

/*
 *  @author Administrator
 *  @version V1.0
 *  @Project smartdeviceplatgorm
 *  @Package com.qf.service.impl
 *  @Description
 *  @Date2022/3/14 0014 17:11
 */

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.bean.SysUserInfo;
import com.qf.enums.EmptyType;
import com.qf.enums.LoginResultEnum;
import com.qf.event.MyLoginEvent;
import com.qf.exception.AddDataException;
import com.qf.exception.LoginException;
import com.qf.exception.MyException;
import com.qf.mapper.SysUserInfoMapper;
import com.qf.service.SysUserInfoService;
import com.qf.utils.MD5Utils;
import com.qf.utils.MyStringUtils;
import com.qf.utils.ResultCode;
import com.qf.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;


@Service
@Transactional
public class SysUserInfoServiceImpl implements SysUserInfoService {
    private int count=0;
    private SysUserInfoMapper sysUserInfoMapper;
    private ApplicationContext context;
    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    Logger logger = LoggerFactory.getLogger(SysUserInfoServiceImpl.class);
    @Autowired
    public void setSysUserInfoMapper(SysUserInfoMapper sysUserInfoMapper) {
        this.sysUserInfoMapper = sysUserInfoMapper;
    }

    @Override
    public SysUserInfo findById(Integer userid) {
        return  sysUserInfoMapper.findById(userid);
    }

    @Override
    public PageInfo<SysUserInfo> findAllSysUserInfo(int pageSize, int pageNum) {
        PageHelper.offsetPage(pageNum,pageSize);
        List<SysUserInfo> sysUserInfosList=sysUserInfoMapper.findAllSysUserInfo();
        PageInfo<SysUserInfo> pageInfo = new PageInfo<>(sysUserInfosList);
        return pageInfo;
    }

    @Override
    public void addSysUserInfo(SysUserInfo sysUserInfo) {
        System.err.println(sysUserInfo);
        //数据校验,应该传递的数据必须传递,数据是不是空的,需要什么数据,只有对象自己知道
        Assert.isTrue(!sysUserInfo.isEmpty(EmptyType.ADD), () -> {
            throw new AddDataException("数据为空", ResultCode.DATA_NULL);
        });
        //数据格式的校验
        //手机号校验
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getPhone(),MyStringUtils.mobileRegex),()->{
            throw new AddDataException("手机号不合法", ResultCode.PHONE_REG_ERROR);
        });
        //校验邮箱
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getEmail(),MyStringUtils.emaiRegex),()->{
            throw new AddDataException("邮箱不合法", ResultCode.EMAIL_REG_ERROR);
        });
        //校验唯一的数据
        //用户名 手机号和邮箱必须检查
        //按照用户名查询一下
        Assert.isNull(sysUserInfoMapper.findByUsername(sysUserInfo.getUsername()),()->{
            throw new AddDataException("用户名已存在", ResultCode.USER_EXIST);
        });
        //按照手机号检查
        Assert.isNull(sysUserInfoMapper.findByPhone(sysUserInfo.getPhone(),null),()->{
            throw new AddDataException("手机号已存在", ResultCode.PHONE_EXIST);
        });
        //按照邮箱检查
        Assert.isNull(sysUserInfoMapper.findByEmail(sysUserInfo.getEmail(),null),()->{
            throw new AddDataException("邮箱已存在", ResultCode.EMAIL_EXIST);
        });
        //生成盐
        String salf = MD5Utils.getRandomString(10);
        sysUserInfo.setPwdSalt(salf);
        //生成密码
        String pwd = MD5Utils.getMd5(sysUserInfo.getPassword(), salf, 1024);
        sysUserInfo.setPassword(pwd);
        //设置默认的数据
        sysUserInfo.setCreateTime(new Date());
        //检查当前登录的用户,如果是管理员,设置管理员的信息,如果没有用户就是用户自己注册的
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户");
        //保存到数据库
        sysUserInfoMapper.addSysUserInfo(sysUserInfo);
        logger.error("添加数据成功");

    }

    @Override
    public SysUserInfo findByUsername(String username) {
        return sysUserInfoMapper.findByUsername(username);
    }

    @Override
    public SysUserInfo findByEmail(String email) {
        return sysUserInfoMapper.findByEmail(email,null);
    }

    @Override
    public SysUserInfo findByPhone(String phone) {
        return sysUserInfoMapper.findByPhone(phone,null);
    }

    @Override
    public SysUserInfo findByUsernameAndPassword(String userName, String passWord) {
//        if(userName.length()<1||"".equals(userName)){
//            throw new MyException("用户名为空", ResultCode.USERNAME_EMPTY);
//        }
//        if(passWord.length()<1||"".equals(passWord)){
//            throw new MyException("密码为空", ResultCode.PASSWORD_EMPTY);
//        }

        Assert.hasLength(userName,()->{
            throw new LoginException("用户名为空", ResultCode.USERNAME_EMPTY);
        });
        Assert.hasLength(passWord,()->{
            throw new LoginException("密码为空", ResultCode.PASSWORD_EMPTY);
        });

        SysUserInfo byUsernameAndPassword = sysUserInfoMapper.findByUsernameAndPassword(userName);
        Assert.notNull(byUsernameAndPassword,()->{
            throw new MyException("用户不存在", ResultCode.USERNAME_PASSWORD_ERROR);
        });

        passWord = MD5Utils.getMd5(passWord, byUsernameAndPassword.getPwdSalt(), 1024);
        System.err.println(passWord+"-------"+byUsernameAndPassword.getPassword());
//        Assert.isTrue(!(passWord==byUsernameAndPassword.getPassword()),()->{
//
//        });
        if(!passWord.equals(byUsernameAndPassword.getPassword())){
            count+=1;
            if (count>=3) {
                CompletableFuture.runAsync(() -> {
                    stopLog(byUsernameAndPassword.getUId());
                });
            }
            context.publishEvent(new MyLoginEvent(LoginResultEnum.FAIL,byUsernameAndPassword.getUsername()));
            if(byUsernameAndPassword.getStatus()!=1){
                throw new MyException("用户状态异常", ResultCode.USERNAME_PASSWORD_ERROR);
            }
            throw new MyException("用户名或密码错误", ResultCode.USERNAME_PASSWORD_ERROR);

        }
        sysUserInfoMapper.updateCurrentTime(byUsernameAndPassword.getUId(),new Date());
        if(byUsernameAndPassword.getLastLogin()==null){
            sysUserInfoMapper.updateLastTime(byUsernameAndPassword.getUId(),new Date());
        }else {
            sysUserInfoMapper.updateLastTime(byUsernameAndPassword.getUId(),byUsernameAndPassword.getCurrentLogin());
        }
        //防止密码和密码盐泄露到前端
        byUsernameAndPassword.setPassword(null);
        byUsernameAndPassword.setPwdSalt(null);
        //记录日志
        context.publishEvent(new MyLoginEvent(LoginResultEnum.SUCCESS,byUsernameAndPassword.getUsername()));
        return byUsernameAndPassword;
    }

    @Override
    public void stopLog(Integer id) {
        sysUserInfoMapper.stopLog(id);
    }

    @Override
    public void updateLastTime(Integer id,Date date) {
        sysUserInfoMapper.updateLastTime(id,date);
    }

    @Override
    public void updateCurrentTime(Integer id,Date date) {
        sysUserInfoMapper.updateLastTime(id,date);
    }

    @Override
    public void updateSysUserInfo(SysUserInfo sysUserInfo) {
        SysUserInfo loginUser = SecurityUtils.getLoginUser();

        Assert.notNull(loginUser,()->{
            throw new MyException("没有登录，请先登录", ResultCode.LOGIN_NOT);
        });
        sysUserInfo.setUId(loginUser.getUId());
        //数据校验,应该传递的数据必须传递,数据是不是空的,需要什么数据,只有对象自己知道
        Assert.isTrue(!sysUserInfo.isEmpty(EmptyType.UPDATE), () -> {
            throw new AddDataException("数据为空,不需要修改！", ResultCode.DATA_NULL);
        });

        //数据格式的校验
        //手机号校验
        if(sysUserInfo.getPhone()!=null&&!("".equals(sysUserInfo.getPhone()))){
            Assert.isTrue(MyStringUtils.check(sysUserInfo.getPhone(),MyStringUtils.mobileRegex),()->{
                throw new AddDataException("手机号不合法", ResultCode.PHONE_REG_ERROR);
            });
            Assert.isNull(sysUserInfoMapper.findByPhone(sysUserInfo.getPhone(),SecurityUtils.getLoginUser().getUId()),()->{
                throw new AddDataException("手机号已存在", ResultCode.PHONE_EXIST);
            });
        }
        //校验邮箱
        if(sysUserInfo.getEmail()!=null&&!("".equals(sysUserInfo.getEmail()))){
            Assert.isTrue(MyStringUtils.check(sysUserInfo.getEmail(),MyStringUtils.emaiRegex),()->{
                throw new AddDataException("邮箱不合法", ResultCode.EMAIL_REG_ERROR);
            });
            //按照邮箱检查
            Assert.isNull(sysUserInfoMapper.findByEmail(sysUserInfo.getEmail(),SecurityUtils.getLoginUser().getUId()),()->{
                throw new AddDataException("邮箱已存在", ResultCode.EMAIL_EXIST);
            });
        }

        //判断用手机号和邮箱是不是跟已登录的一模一样，如果一样就没必要修改
        if (sysUserInfo.getPhone() == loginUser.getPhone()) {
            sysUserInfo.setPhone(null);
        }
        if (sysUserInfo.getEmail() == loginUser.getEmail()) {
            sysUserInfo.setEmail(null);
        }
        //校验唯一的数据
        //用户名 手机号和邮箱必须检查
        //按照用户名查询一下
        //按照手机号检查




        sysUserInfoMapper.updateSysUserInfo(sysUserInfo);
    }

    @Override
    public void updatePassword(String password,Integer uId) {
        SysUserInfo loginUser = SecurityUtils.getLoginUser();
        Assert.notNull(loginUser,()->{
            throw new MyException("没有登录，请登录！", ResultCode.LOGIN_NOT);
        });
        String pwd = MD5Utils.getMd5(password, loginUser.getPwdSalt(), 1024);
        sysUserInfoMapper.updatePassword(pwd);
    }
}
